# 事务的四大特征

事务(Transaction)是以可控的方式对数据资源进行访问的一组操作

  1. 原子性(Atomicity):原子性要求事务所包含的全部操作是一个不可分割的整体,这些操作要么全部提交成功,要么只要其中一个操作失败,就全部失败
  2. 一致性(Consistency):若数据资源在事务执行之前处于某个数据一致性状态(如两个账户金额总和为 1000),一致性要求事务执行后依然保持数据间的一致性状态(A 向 B 转账 500,总和依然为 1000)
  3. 隔离性(Isolation):事务的隔离性主要规定了各个事务之间相互影响的程度,隔离性的概念主要面向数据的并发访问(Concurrency)
  4. 持久性(Durability):当事务提交或者回滚后,数据库会持久化的更新保存数据

# 事务的四大隔离级别

并发访问可能产生的问题

  • 脏读(Dirty Read):一个事务读取到另一个事务中没有提交的数据。如果事务 1 读取到事务 2 还未提交的数据,事务 2 回滚,则事务 1 读取到的数据就是一笔脏数据

  • 不可重复读(Non-Repeatable Read):也叫虚读,指的是同一个事务在整个事务过程中,对同一笔数据进行读取,每次读取的结果都不同。如事务 1 在事务 2 的更新操作执行前读取一次,在事务 2 更新操作后再读取同一笔数据一次,两次结果不同

  • 幻读(Phantom Read):指的是同样一个查询,在整个事务过程中多次执行后,查询所得的结果集是不一样的。幻读针对的是多笔记录

幻读和不可重复读区别

幻读是读到之前没有出现过的数据(新增或删除),不可重复读是同一条数据多次读结果不同


隔离级别

  • Read Uncommitted无法解决脏读、不可重复读、幻读
    最低的隔离级别,一个事务可以读取另一个事务还未提交的更新结果,以较低隔离度来寻求较高的性能

  • Read Committed可以避免脏读,无法解决不可重复读、幻读
    大部分数据库采用的默认隔离级别,一个事务的更新结果只有在事务提交后,另一个事务才可能读取到

  • Repeatable Read可以避免脏读、不可重复读,无法解决幻读
    该隔离级别可以保证在整个事务的过程中,对同一笔数据的读取结果是相同的,不管其他事务是否同时在对同一笔数据进行更新,也不管其他事务对同一笔数据的更新提交与否

  • Serializable可以避免全部问题
    最为严格的隔离级别,所有事务操作都必须依次顺序进行,是最安全的隔离级别,但同时也是性能最差的隔离级别。因为该隔离级别极大影响系统性能,所以很少使用,通常情况下,会采用其他隔离级别加上相应的并发锁机制来控制对数据的访问

# 基本操作

-- MySQL数据库中事务默认自动提交,一条DML(增删改)语句会自动提交一次事务(Oracle默认手动)
-- 手动开启事务后,如果语句执行完毕后没有提交,则程序终止时会自动回滚

# 可以修改事务的默认提交方式
SELECT @@autocommit; -- 1: 自动提交 0: 手动提交
SET @@autocommit = 0;


-- 1. 开启事务
START TRANSACTION;

# A 向 B 转账50
UPDATE account SET balance = balance - 50 WHERE name = 'A';
UPDATE account SET balance = balance + 50 WHERE name = 'B';

-- 2. 如果以上两条语句执行完毕后发现出现错误,则回滚
ROLLBACK;

-- 3. 如果没有问题。正确执行,则提交事务
COMMIT;

-- 数据库设置隔离级别
# 查询隔离级别
SELECT @@tx_isolation; -- 默认 REPEATABLE READ

# 设置隔离级别
SET GLOBAL TRANSACTION ISOLATION LEVEL 级别字符串; -- 重新连接数据后生效
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
Last Updated: 7/1/2020, 2:19:02 AM